package edu.pku.sei.modeler.model.notation.shape;

import java.util.Iterator;
import java.util.List;

import org.eclipse.draw2d.geometry.Rectangle;
import org.w3c.dom.Element;

import edu.pku.sei.gefcommon.common.resourceManager.Color;
import edu.pku.sei.gefcommon.descriptor.annotation.EnumerationProperty;
import edu.pku.sei.gefcommon.descriptor.annotation.FieldProperty;
import edu.pku.sei.gefcommon.descriptor.annotation.MethodProperty;
import edu.pku.sei.modeler.model.notation.core.ShapeConstance;
import edu.pku.sei.modeler.model.notation.core.ShapeNode;
import edu.pku.sei.modeler.model.notation.layout.Layout;
import edu.pku.sei.modeler.model.xml.XMLUtility;
import edu.pku.sei.modeler.model.notation.core.NotationPackage;

public class Shape extends ShapeNode {
	@FieldProperty(id="SHAPE_RESIZEABLE",catalog="Shape",name="Resizeable")
	private boolean resizeable;
	private Layout layout;
	//@FieldProperty(id="SHAPE_LINE_COLOR",catalog="Shape",name="Line Color")
	protected Color lineColor;
	//@FieldProperty(id="SHAPE_FILL_COLOR",catalog="Shape",name="Fill Color")
	protected Color fillColor;
	
	public void doLayout(){
		if(layout==null||layout.getLayoutStrategy()==Layout.TYPE_NONE){
			removeAllSlaves();
		} else {
			layout.doLayout();
		}
	}
	
	
	public Shape() {
		super();
		resizeable = true;
		lineColor = Color.BLACK;
		fillColor = Color.WHITE;
		layout = new Layout(this,Layout.TYPE_VERTICAL_FLOW);
	}
	public Layout getLayout() {
		return layout;
	}
	@MethodProperty(id="SHAPE_LAYOUT_STRATEGY",catalog="Shape",name="Layout",setter="setLayoutStrategy")
	@EnumerationProperty(strings={"NONE","VERTICAL FLOW","HORIZONTAL FLOW","BORDER","VECTORGRAPH","FREEDOM"})
	public int getLayoutStrategy(){
		return layout.getLayoutStrategy();
	}
	public void setLayoutStrategy(int strategy) {
		layout.setLayoutStrategy(strategy);
		if(strategy==Layout.TYPE_NONE) {
			removeAllSlaves();
		} else {
			List slaves = getSlaves();
			Iterator it = slaves.iterator();
			while(it.hasNext()){
				ShapeNode s = (ShapeNode)it.next();
				changeChildBound(s,s.getBound());
			}
		}
	}
	
	public boolean isResizeable() {
		return resizeable;
	}
	public void setResizeable(boolean resizeable) {
		this.resizeable = resizeable;
	}
// end
	public void removeAllSlaves(){
		getSlaves().clear();
		layout.clearConstraint();
		this.fireStructureChange(ShapeConstance.REFRESH_ALL, null);
	}
	public List getSlaves() {
		return getChildren();
	}
	public void addSlaveWithConstraint(ShapeNode s,Object cons) {
		layout.putConstraint(s, cons);
		this.addChild(s, ShapeConstance.REFRESH_ALL);
	}
	
	public void changeChildBound(ShapeNode child,Rectangle bound) {
		if(getSlaves().contains(child)==false) return;
		Object cons = layout.createLayoutConstraint(bound);
		layout.putConstraint(child, cons);
		this.firePropertyChange(ShapeConstance.REFRESH_VIEW, null, cons);
	}
	
	public void addSlaveWithInitBounds(ShapeNode s,Rectangle initBound) {
		Rectangle mbound = getBound();
		if(initBound==null){
			initBound = Rectangle.SINGLETON;
			initBound.setLocation(mbound.x,mbound.y);
			initBound.setSize(50,50);
		}
		Object cons = layout.createLayoutConstraint(initBound);
		layout.putConstraint(s, cons);
		this.addChild(s, ShapeConstance.REFRESH_ALL);
	}
	public void removeSlave(ShapeNode s){
		layout.removeConstraint(s);
		this.removeChild(s, ShapeConstance.REFRESH_ALL);
	}

	@MethodProperty(id="SHAPE_FILL_COLOR",catalog="Shape",name="Fill Color",setter="setFillColor")
	public Color getFillColor() {
		return fillColor;
	}


	public void setFillColor(Color fillColor) {
		this.fillColor = fillColor;
		this.firePropertyChange(ShapeConstance.REFRESH_VIEW, null, fillColor);
	}

	@MethodProperty(id="SHAPE_LINE_COLOR",catalog="Shape",name="Line Color",setter="setLineColor")
	public Color getLineColor() {
		return lineColor;
	}

	
	public void setLineColor(Color lineColor) {
		this.lineColor = lineColor;
		this.firePropertyChange(ShapeConstance.REFRESH_VIEW, null, lineColor);
	}
	
	@MethodProperty(id="SHAPE_LAYOUT_CONSTRAINT",catalog="Shape",name="Constraint")
	public Object getLayoutConstraint(){
		ShapeNode node = getParent();
		if(node==null||!(node instanceof Shape)) return null;
		else return ((Shape)node).getLayout().getConstraint(this);
	}
	//add by fengchao
	public void serialize(Element root) {
		super.serialize(root);
		XMLUtility.xmlInstance.serializeAttribute(root, NotationPackage.SHAPE_RESIZEABLE, resizeable);
		XMLUtility.xmlInstance.serializeAttribute(root, NotationPackage.SHAPE_LAYOUT, getLayoutStrategy());
		
		XMLUtility.xmlInstance.serializeAttribute(root, NotationPackage.SHAPE_FILLCOLOR_RED, fillColor.red);
		XMLUtility.xmlInstance.serializeAttribute(root, NotationPackage.SHAPE_FILLCOLOR_GREEN, fillColor.green);
		XMLUtility.xmlInstance.serializeAttribute(root, NotationPackage.SHAPE_FILLCOLOR_BLUE, fillColor.blue);
		
		XMLUtility.xmlInstance.serializeAttribute(root, NotationPackage.SHAPE_LINECOLOR_RED, lineColor.red);
		XMLUtility.xmlInstance.serializeAttribute(root, NotationPackage.SHAPE_LINECOLOR_GREEN, lineColor.green);
		XMLUtility.xmlInstance.serializeAttribute(root, NotationPackage.SHAPE_LINECOLOR_BLUE, lineColor.blue);
	}
	public void deSerialize(Element root) {
		super.deSerialize(root);
		this.resizeable = XMLUtility.xmlInstance.deSerializeBoolean(root, NotationPackage.SHAPE_RESIZEABLE);
		int strategy = XMLUtility.xmlInstance.deSerializeInt(root, NotationPackage.SHAPE_LAYOUT);
		setLayoutStrategy(strategy);
		
		int fillColorRed = XMLUtility.xmlInstance.deSerializeInt(root, NotationPackage.SHAPE_FILLCOLOR_RED);
		int fillColorGreen = XMLUtility.xmlInstance.deSerializeInt(root, NotationPackage.SHAPE_FILLCOLOR_GREEN);
		int fillColorBlue = XMLUtility.xmlInstance.deSerializeInt(root, NotationPackage.SHAPE_FILLCOLOR_BLUE);
		fillColor = new Color(fillColorRed, fillColorGreen, fillColorBlue);
		
		int lineColorRed = XMLUtility.xmlInstance.deSerializeInt(root, NotationPackage.SHAPE_LINECOLOR_RED);
		int lineColorGreen = XMLUtility.xmlInstance.deSerializeInt(root, NotationPackage.SHAPE_LINECOLOR_GREEN);
		int lineColorBlue = XMLUtility.xmlInstance.deSerializeInt(root, NotationPackage.SHAPE_LINECOLOR_BLUE);
		lineColor = new Color(lineColorRed, lineColorGreen, lineColorBlue);
	}
	//end add
}
